package com.cskaoyan.aspect;

import com.cskaoyan.bean.Admin;
import com.cskaoyan.bean.BaseRespVo;
import com.cskaoyan.bean.Log;
import com.cskaoyan.bean.auth.bo.AuthLoginBo;
import com.cskaoyan.config.ActionType;
import com.cskaoyan.service.LogService;
import com.cskaoyan.util.HttpUtils;
import com.cskaoyan.util.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class LogAspect {

    @Autowired
    private LogService logService;

    @Pointcut("execution(* com..controller.Admin*.*(..))")
    public void adminLogPointCont() {

    }

    /**
     * 此切面处理 后台管理系统 记录 admin账号的所有操作日志
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("adminLogPointCont()")
    public Object adminActionLog(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = HttpUtils.getHttpRequest();
        String requestURI = request.getRequestURI();

        Subject subject = SecurityUtils.getSubject();
        Object principal =  subject.getPrincipal();

        Admin admin = null;

        String adminUsername = null;

        String remoteAddr = request.getRemoteAddr();

        String action = StringUtils.uriToPermission(requestURI);
        Integer type = ActionType.getType(action);
        Boolean status;
        String result = null;
        String comment = null;
        Exception exception = null;
        BaseRespVo baseRespVo = null;

        if (principal instanceof Admin) {
            admin = (Admin) principal;
            adminUsername = admin.getUsername();
        }

        try {
            baseRespVo = (BaseRespVo) joinPoint.proceed();
            String errmsg = baseRespVo.getErrmsg();
            long errno = baseRespVo.getErrno();
            status = errno == 0 ? true : false;
            result = errmsg;
        } catch (Exception e) {
            exception = e;
            status = false;
            //数据库字段长度保护
            comment = getExceptionMessage(e);
        }
        //封装log
        Log log = new Log();
        log.setIp(remoteAddr);
        log.setType(type);
        log.setAction(action);
        log.setStatus(status);
        log.setResult(result);
        log.setComment(comment);

        if ("/admin/auth/login".equals(requestURI)) {
            Object[] args = joinPoint.getArgs();
            AuthLoginBo authLoginBo = (AuthLoginBo) args[0];
            adminUsername = authLoginBo.getUsername();
        }



        log.setAdmin(adminUsername);

        //存入数据库
        logService.createLog(log);

        //抛出异常
        if (exception != null) {
            throw exception;
        }

        //正常返回
        return baseRespVo;

    }

    private String getExceptionMessage(Exception e) {

        String exmsg = e.getMessage();
        if (exmsg == null) {
            return e.toString();
        }
        String comment;
        if (exmsg.length() <= 240) {
            comment = exmsg;
        } else {
            StringBuilder sb = new StringBuilder();
            StackTraceElement[] stackTrace = e.getStackTrace();
            for (StackTraceElement element : stackTrace) {
                String methodName = element.getMethodName();
                int lineNumber = element.getLineNumber();
                sb.append(methodName + " " + lineNumber + ";");
            }
            comment = sb.toString();
            if (comment.length() > 240) {
                comment = comment.substring(0, 240);
            }
        }
        return comment;
    }


}
